![]() |
AVR1636 Configurable PMSM Sensorless FOC using the XMEGA
1.0
|
PMSM Sensorless Field Oriented Control using the ATXmega16D4 Atmel Studio 6 (Version: 6.0.1996 - Service Pack 2) using AVR GCC Compiler -02 optimization Installed Packages: AVRGCC - 3.4.1.95 AVR Toolchain 8 Bit Version: 3.4.1.830 - GCC 4.6.2 Program Memory Usage : 6996 bytes 34.2 % Full Data Memory Usage : 162 bytes 7.9 % Full. More...
#include <stdint.h>#include <avr/io.h>#include <avr/pgmspace.h>#include <avr/interrupt.h>#include <avr/eeprom.h>Go to the source code of this file.
PMSM Sensorless Field Oriented Control using the ATXmega16D4 Atmel Studio 6 (Version: 6.0.1996 - Service Pack 2) using AVR GCC Compiler -02 optimization Installed Packages: AVRGCC - 3.4.1.95 AVR Toolchain 8 Bit Version: 3.4.1.830 - GCC 4.6.2 Program Memory Usage : 6996 bytes 34.2 % Full Data Memory Usage : 162 bytes 7.9 % Full.
Definition in file AVR1636 - Firmware.c.
| #define ADC_MUX_bm 0x3F |
Definition at line 161 of file AVR1636 - Firmware.c.
| #define ADC_MUX_I (ADC_CH_MUXPOS2_bm) |
Definition at line 168 of file AVR1636 - Firmware.c.
Referenced by init_adc(), and ISR().
| #define ADC_MUX_VBUS (ADC_CH_MUXPOS2_bm | ADC_CH_MUXPOS1_bm) |
Definition at line 166 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define ADC_MUX_X 0 |
Definition at line 164 of file AVR1636 - Firmware.c.
| #define ADC_PRESCALER 4 |
Definition at line 160 of file AVR1636 - Firmware.c.
| #define counter variable_table[15] |
Definition at line 374 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define CURRENT_SETTLING_TIME 14 |
Definition at line 174 of file AVR1636 - Firmware.c.
| #define data_watch variable_table[2 + VARIABLE_TABLE_SIZE] |
Definition at line 381 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define DEAD_TIME (PWM_DB/PWM_PRESCALER) |
Definition at line 173 of file AVR1636 - Firmware.c.
| #define e_a_display variable_table[7] |
Definition at line 361 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define e_d_display variable_table[10] |
Definition at line 366 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define EEPROM_TABLE_SIZE 32 |
Definition at line 192 of file AVR1636 - Firmware.c.
Referenced by ISR(), read_eeprom(), and write_eeprom().
| #define HALF_SCALE 128 |
Definition at line 171 of file AVR1636 - Firmware.c.
Referenced by calibrate_current(), and ISR().
| #define HEADER_SIZE 64 |
Definition at line 195 of file AVR1636 - Firmware.c.
| #define i_a_display variable_table[2] |
Definition at line 355 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define i_b_display variable_table[3] |
Definition at line 356 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define i_d_display variable_table[8] |
Definition at line 363 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define i_error_limit variable_table[13 + VARIABLE_TABLE_SIZE] |
Definition at line 395 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define i_k_scaling variable_table[14 + VARIABLE_TABLE_SIZE] |
Definition at line 396 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define i_ki variable_table[16 + VARIABLE_TABLE_SIZE] |
Definition at line 398 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define i_kp variable_table[15 + VARIABLE_TABLE_SIZE] |
Definition at line 397 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define i_limit variable_table[11 + VARIABLE_TABLE_SIZE] |
Definition at line 392 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define I_MAX 120 |
Definition at line 132 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define i_q_display variable_table[9] |
Definition at line 364 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define i_reg_scaling variable_table[12 + VARIABLE_TABLE_SIZE] |
Definition at line 394 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define input_cmd_display variable_table[4 + VARIABLE_TABLE_SIZE] |
Definition at line 383 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define ir_a_display variable_table[5] |
Definition at line 359 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define l_didt_a_display variable_table[6] |
Definition at line 360 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define l_phase variable_table[31 + VARIABLE_TABLE_SIZE] |
Definition at line 417 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define l_scaling variable_table[30 + VARIABLE_TABLE_SIZE] |
Definition at line 416 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define MESSAGE_SIZE (HEADER_SIZE + VARIABLE_TABLE_SIZE + EEPROM_TABLE_SIZE +1) |
Definition at line 198 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define mode variable_table[3 + VARIABLE_TABLE_SIZE] |
Definition at line 382 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define ONE_OVER_SQRT_THREE 148 |
Definition at line 184 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define ONE_OVER_THREE 85 |
Definition at line 182 of file AVR1636 - Firmware.c.
| #define osc_cal_adj variable_table[1 + VARIABLE_TABLE_SIZE] |
Definition at line 379 of file AVR1636 - Firmware.c.
Referenced by write_oscillator_cal().
| #define osc_error variable_table[14] |
Definition at line 372 of file AVR1636 - Firmware.c.
Referenced by test_oscillator().
| #define p_error_limit variable_table[22 + VARIABLE_TABLE_SIZE] |
Definition at line 407 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define p_gravity variable_table[26 + VARIABLE_TABLE_SIZE] |
Definition at line 411 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define p_k_scaling variable_table[23 + VARIABLE_TABLE_SIZE] |
Definition at line 408 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define p_ki variable_table[25 + VARIABLE_TABLE_SIZE] |
Definition at line 410 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define p_kp variable_table[24 + VARIABLE_TABLE_SIZE] |
Definition at line 409 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define p_reg_scaling variable_table[21 + VARIABLE_TABLE_SIZE] |
Definition at line 406 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define PWM_CHANNEL_A TCC0_CCABUF |
Definition at line 123 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define PWM_CHANNEL_B TCC0_CCBBUF |
Definition at line 124 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define PWM_CHANNEL_C TCC0_CCCBUF |
Definition at line 125 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define PWM_CHANNEL_D TCC0_CCDBUF |
Definition at line 126 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define PWM_DB 24 |
Definition at line 119 of file AVR1636 - Firmware.c.
Referenced by init_pwm().
| #define PWM_HALF 127 |
Definition at line 118 of file AVR1636 - Firmware.c.
Referenced by init_pwm(), and ISR().
| #define PWM_MAX 256 |
Definition at line 117 of file AVR1636 - Firmware.c.
Referenced by init_pwm(), and ISR().
| #define PWM_PERIODS 960 |
Definition at line 135 of file AVR1636 - Firmware.c.
Referenced by test_oscillator().
| #define PWM_PRESCALER 4 |
Definition at line 116 of file AVR1636 - Firmware.c.
| #define PWM_TIMER_ISR_VECTOR TCC0_CCD_vect |
Definition at line 121 of file AVR1636 - Firmware.c.
| #define r_phase variable_table[29 + VARIABLE_TABLE_SIZE] |
Definition at line 415 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define r_scaling variable_table[28 + VARIABLE_TABLE_SIZE] |
Definition at line 414 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define RXD_PIN PIN2_bm |
Definition at line 147 of file AVR1636 - Firmware.c.
Referenced by test_oscillator().
| #define RXD_PIN_0 0 |
Definition at line 149 of file AVR1636 - Firmware.c.
Referenced by test_oscillator().
Definition at line 150 of file AVR1636 - Firmware.c.
Referenced by test_oscillator().
| #define RXD_pin_test (PORTD_IN & RXD_PIN) |
Definition at line 148 of file AVR1636 - Firmware.c.
| #define s_error_limit variable_table[7 + VARIABLE_TABLE_SIZE] |
Definition at line 387 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define s_k_scaling variable_table[8 + VARIABLE_TABLE_SIZE] |
Definition at line 388 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define s_ki variable_table[10 + VARIABLE_TABLE_SIZE] |
Definition at line 390 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define s_kp variable_table[9 + VARIABLE_TABLE_SIZE] |
Definition at line 389 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define s_reg_rate variable_table[5 + VARIABLE_TABLE_SIZE] |
Definition at line 385 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define s_reg_scaling variable_table[6 + VARIABLE_TABLE_SIZE] |
Definition at line 386 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define SAMPLE_1_OFFSET (SAMPLE_HOLD_TIME) |
Definition at line 176 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define SAMPLE_2_OFFSET (TRIGGER_OFFSET + DEAD_TIME + CURRENT_SETTLING_TIME) |
Definition at line 177 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define SAMPLE_HOLD_TIME 11 |
Definition at line 175 of file AVR1636 - Firmware.c.
| #define SAMPLE_WINDOW (SAMPLE_1_OFFSET + SAMPLE_2_OFFSET) |
Definition at line 179 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define speed_display variable_table[12] |
Definition at line 369 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define speed_max variable_table[20 + VARIABLE_TABLE_SIZE] |
Definition at line 404 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define speed_min variable_table[19 + VARIABLE_TABLE_SIZE] |
Definition at line 403 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define speed_scale variable_table[18 + VARIABLE_TABLE_SIZE] |
Definition at line 402 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define SQRT_THREE_OVER_TWO 222 |
Definition at line 186 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define TEST_PIN PIN6_bm |
Definition at line 153 of file AVR1636 - Firmware.c.
| #define TEST_pin_hi PORTC_OUTSET = TEST_PIN |
Definition at line 155 of file AVR1636 - Firmware.c.
Referenced by calibrate_current(), and ISR().
| #define TEST_pin_lo PORTC_OUTCLR = TEST_PIN |
Definition at line 154 of file AVR1636 - Firmware.c.
Referenced by init_test_pin(), and ISR().
| #define TEST_pin_out PORTC_DIRSET |= TEST_PIN |
Definition at line 156 of file AVR1636 - Firmware.c.
Referenced by init_test_pin().
| #define TEST_pin_totem PORTC_PIN6CTRL |= PORT_OPC_TOTEM_gc |
Definition at line 157 of file AVR1636 - Firmware.c.
Referenced by init_test_pin().
| #define theta variable_table[13] |
Definition at line 370 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define TRIGGER_OFFSET 1 |
Definition at line 172 of file AVR1636 - Firmware.c.
| #define TWO_OVER_SQRT_THREE 148 |
Definition at line 185 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define TWO_OVER_THREE 171 |
Definition at line 183 of file AVR1636 - Firmware.c.
| #define TXD_PIN PIN3_bm |
Definition at line 141 of file AVR1636 - Firmware.c.
Definition at line 142 of file AVR1636 - Firmware.c.
Definition at line 143 of file AVR1636 - Firmware.c.
Referenced by init_uart().
| #define TxD_pin_out PORTD_DIRSET |= TXD_PIN |
Definition at line 144 of file AVR1636 - Firmware.c.
Referenced by init_uart().
| #define TxD_pin_totem PORTD_PIN3CTRL |= PORT_OPC_TOTEM_gc |
Definition at line 145 of file AVR1636 - Firmware.c.
| #define u_a_display variable_table[4] |
Definition at line 358 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define u_scaling variable_table[27 + VARIABLE_TABLE_SIZE] |
Definition at line 413 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define UART_DATA_REGISTER USARTD0_DATA |
Definition at line 138 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define UART_STATUS_RECIEVE_TEST (USARTD0_STATUS & USART_RXCIF_bm) |
Definition at line 139 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define v_a_display variable_table[0] |
Definition at line 352 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define v_b_display variable_table[1] |
Definition at line 353 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define v_bus variable_table[11] |
Definition at line 368 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define v_bus_min variable_table[0 + VARIABLE_TABLE_SIZE] |
Definition at line 377 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define v_limit variable_table[17 + VARIABLE_TABLE_SIZE] |
Definition at line 400 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define V_MAX 123 |
Definition at line 130 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define V_MAX_SQUARED (V_MAX*V_MAX) |
Definition at line 131 of file AVR1636 - Firmware.c.
Referenced by ISR().
| #define VARIABLE_TABLE_SIZE 16 |
Definition at line 189 of file AVR1636 - Firmware.c.
Referenced by ISR(), read_eeprom(), and write_eeprom().
| void calibrate_current | ( | void | ) |
Current Sense Calibration.
Measures the DC offset of the current sense shunt and the resistive divider that biases the shunt voltage above ground when the current is zero. The offset value is used in all current reconstruction calculations.
Definition at line 811 of file AVR1636 - Firmware.c.
References HALF_SCALE, i_sample_1, i_sample_2, i_sample_offset, pwm_counter, and TEST_pin_hi.
Referenced by main().
{
uint8_t bit_test;
AWEXC_OUTOVEN = 0x00; //Make sure all PWM outputs are disabled
while (i_sample_offset == 0)
{
cli();
bit_test = pwm_counter;
sei();
if (bit_test == 3)
{
TEST_pin_hi;
cli();
if ((i_sample_1 > 10) && (i_sample_1 == i_sample_2))
{
i_sample_offset = HALF_SCALE - i_sample_1;
}
sei();
}
}
AWEXC_OUTOVEN = 0x3F; //Enable all PWM outputs
}
| void init_adc | ( | void | ) |
Initializes ADC.
ADC is initialized in single ended mode, Left Aligned for 8 bit values Using the 1V internal reference. The conversion is triggered by the port C timer 0 channel D through the event system.
Definition at line 524 of file AVR1636 - Firmware.c.
References ADC_MUX_I.
Referenced by main().
{
// CTRLA - ADC Control Register A
// Bit 0 – ENABLE: ADC Enable
// CTRLB - ADC Control Register B
// Bit 4 - CONVMODE: ADC Conversion Mode: 0 = unsigned mode
// Bits 2:1 - RESOLUTION[1:0]: ADC Conversion Result Resolution
ADCA_CTRLB = ADC_RESOLUTION1_bm; //8 bit resolution
// REFCTRL - ADC Reference Control register
// Bits 6:4 – REFSEL[2:0]:ADC Reference Selection: 000 INT1V Internal 1.00V
// Bit 1 – BANDGAP: Bandgap enable
// PRESCALER - ADC Clock Prescaler register
// Bits 2:0 - PRESCALER[2:0]: ADC Prescaler configuration: 001 DIV8 8
ADCA_PRESCALER = ADC_PRESCALER_DIV32_gc;
// CTRL - ADC Channel Control Register
// Bit 7 - START: START Conversion on Channel
// Bits 4:2 - GAIN[2:0]: ADC Gain Factor
// Bit 1:0 - INPUTMODE[1:0]: ADC Input Mode: 01 SINGLEENDED
ADCA_CH0_CTRL = ADC_CH_INPUTMODE_SINGLEENDED_gc;
// MUXCTRL - ADC Channel MUX Control registers
// Bits 6:3 - MUXPOS[3:0]: MUX selection on Positive ADC input
// Bits 1:0 - MUXNEG[1:0]: MUX selection on Negative ADC input
//current sampling
ADCA_CH0_MUXCTRL = ADC_MUX_I;
// CTRLA - ADC Control Register A
// Bit 0 – ENABLE: ADC Enable
ADCA_CTRLA = ADC_ENABLE_bm;
// EVCTRL - ADC Event Control Register
// Bits 5:3 - EVSEL[2:0]: event channel input select: 0 to 3
// Bits 0 - EVACT0: ADC Event Mode
//Enable Event trigger
ADCA_EVCTRL |= ADC_EVACT0_bm;
}
| void init_eventsys | ( | void | ) |
Initializes Event System.
Configures Event System Channel 0 to trigger an ADC conversion off of Compare D Timer/Counter C0. This is used for timing ADC samples for single shunt current reconstruction. The event system signal is brought out to Port D pin 7, used in code development. This can be disabled if the pin needs to be re purposed.
Definition at line 652 of file AVR1636 - Firmware.c.
Referenced by main().
{
// CHnMUX – Event Channel n Multiplexer Register
// 1100 1100 TCxn_CCA Capture or Compare D Timer/Counter C0 event type E
EVSYS_CH0MUX = 0xC7;
// CLKEVOUT - Clock and Event Out Register
// Bit 5:4 - EVOUT[1:0] - Event Output Port:
// 10 = PD7 Event Channel 0 output on Port D pin 7
PORTCFG_CLKEVOUT |= PORTCFG_EVOUT1_bm;
PORTD_DIRSET |= PIN7_bm;
}
| void init_interrupts | ( | void | ) |
Enable interrupts.
Enables the Timer 0 Port C interrupt for Capture/Compare Channel D set to the highest level. Then enables all interrupts levels.
Definition at line 848 of file AVR1636 - Firmware.c.
Referenced by main().
{
cli();
TCC0_INTCTRLB |= (TC0_CCDINTLVL1_bm | TC0_CCDINTLVL0_bm);
PMIC_CTRL |= (PMIC_HILVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_LOLVLEN_bm);
sei();
}
| void init_oscillator | ( | void | ) |
Initializes Oscillator for 32MHz operation.
This function enables the 32MHz internal oscillator then waits for the oscillator to be ready, then switches over the system clock to 32MHz.
Definition at line 434 of file AVR1636 - Firmware.c.
Referenced by main().
{
CCP = CCP_IOREG_gc; // disable register security for oscillator update
OSC_CTRL = OSC_RC32MEN_bm; // enable 32MHz oscillator
while(!(OSC_STATUS & OSC_RC32MRDY_bm))
{
// wait for oscillator to be ready
}
CCP = CCP_IOREG_gc; // disable register security for clock update
CLK_CTRL = CLK_SCLKSEL_RC32M_gc; // switch to 32MHz clock
}
| void init_pwm | ( | void | ) |
Initializes Port C Timer 0 as Three Phase PWM output with Deadtime.
PWM is configured for 31.25kHz operating frequency, 8-bit resolution 32MHz / 4 prescaler / 256 = 31.25kHz Channels A,B, and C along with the AWEX for deadtime to generate three phase PWM. Channel D is used to trigger the ADC, through the event system, for single shunt current reconstruction. Edge aligned PWM is used because it requires the least amount of PWM modification for the ADC sample window.
Definition at line 486 of file AVR1636 - Firmware.c.
References PWM_DB, PWM_HALF, and PWM_MAX.
Referenced by main().
{
PORTC_DIR |= 0x3F; // set as output
TCC0_CTRLA = 0x03; // Prescaler: clk/4
//Bit 7:4 – CCxEN: Compare or Capture Enable
//Bit 2:0 – WGMODE[2:0]: Waveform Generation Mode = 011 SINGLESLOPE
TCC0_CTRLB = 0x03; // Single-slope PWM
TCC0_PER = PWM_MAX-1; //
TCC0_CCA = PWM_HALF; //
TCC0_CCB = PWM_HALF; //
TCC0_CCC = PWM_HALF;
TCC0_CCD = PWM_HALF;
//CTRL - Control Register
//Bit 3:0 - DTICCxEN: Dead-Time Insertion CCx Enable
AWEXC_CTRL = 0x07; //Enable A. B, and C dead time
//Dead-Time Concurrent write to Low and High Side Buffer Registers
AWEXC_DTLS = PWM_DB; // 24 = 750ns
AWEXC_DTHS = PWM_DB; // 24 = 750ns
}
| void init_test_pin | ( | void | ) |
Initializes pin for Code testing function.
Test pin is used on a spare pin to look at code timing using an oscilloscope. This is only for Debugging and benchmarking code TEST_pin_hi; and TEST_pin_lo; are inserted in code to set the pin high and low.
Definition at line 461 of file AVR1636 - Firmware.c.
References TEST_pin_lo, TEST_pin_out, and TEST_pin_totem.
Referenced by main().
| void init_uart | ( | void | ) |
Initializes UART.
The UART is set up for bi directional 115,200 baud to match the maximum standard COM port frequency. The UART is polled in the PWM ISR that makes up the FOC control loop. THe UARt is used for communication to the PC based Atmel Motor Control Configuration Utility.
Definition at line 581 of file AVR1636 - Firmware.c.
References TxD_pin_1, and TxD_pin_out.
Referenced by main().
{
uint16_t bsel = 1047;
uint8_t bscale = 10;
// USART initialization should use the following sequence:
// 1. Set the TxD pin value high, and optionally the XCK pin low.
// 2. Set the TxD and optionally the XCK pin as output.
// 3. Set the baud rate and frame format.
// 4. Set mode of operation (enables XCK pin output in synchronous mode).
// 5. Enable the Transmitter or the Receiver depending on the usage.
TxD_pin_1;
TxD_pin_out;
// DATA - USART I/O Data Register
// USARTD0_DATA
// 115200 @ 32Mhz as calculated from ProtoTalk Calc
// USARTD0_BAUDCTRLA = (uint8_t) bsel;
USARTD0_BAUDCTRLA = (0xFF & bsel);
USARTD0_BAUDCTRLB = (bscale << 4) | (bsel >> 8);
// STATUS - USART Status Register
// USART_RXCIF_bm 0x80 /* Receive Interrupt Flag bit mask. */
// USART_TXCIF_bm 0x40 /* Transmit Interrupt Flag bit mask. */
// USARTD0_STATUS
// BAUDCTRLA - USART Baud Rate Register
// Bit 7:0 - BSEL[7:0]: USART Baud Rate Register
// USARTD0_BAUDCTRLA = 138; //For 115200 Baud, 32MHz clock, BSCALE = 10
// BAUDCTRLB - USART Baud Rate Register
// Bit 7:4 - BSCALE[3:0]: USART Baud Rate Scale factor
// Bit 3:0 - BSEL[11:8]: USART Baud Rate Register
// USARTD0_BAUDCTRLB =
// ( USART_BSCALE3_bm | USART_BSCALE2_bm | USART_BSCALE0_bm);
// CTRLA – USART Control Register A
// Interrupt Level - Unused
USARTD0_CTRLA = 0;
// CTRLC - USART Control Register C
// Bits 7:6 - CMODE[1:0]: USART Communication Mode: 00 = Asynchronous USART
// Bit 2:0 - CHSIZE[2:0]: Character Size: 011 = 8BIT, 8-bit
USARTD0_CTRLC = USART_CHSIZE_8BIT_gc;
// CTRLB - USART Control Register B
// Bit 4 - RXEN: Receiver Enable
// USART_RXEN_bm 0x10 /* Receiver Enable bit mask. */
// Bit 3 - TXEN: Transmitter Enable
// USART_TXEN_bm 0x08 /* Transmitter Enable bit mask. */
USARTD0_CTRLB = (USART_RXEN_bm | USART_TXEN_bm);
}
Interrupt Service Routine for FOC.
This is the main control loop for all Field Oriented Control functions and communication with the Motor Control Configuration Utility.
Definition at line 868 of file AVR1636 - Firmware.c.
References ADC_MUX_I, ADC_MUX_VBUS, adc_user_channel, adc_user_sample, byte_timeout, comp_ki, correction_1, correction_2, cos_theta, count_dir, counter, data_rxd, data_toggle, data_txd, data_watch, e_a, e_a_display, e_alpha, e_b, e_beta, e_c, e_d, e_d_display, e_q, eeprom_number, EEPROM_TABLE_SIZE, error, HALF_SCALE, i_a, i_a_display, i_a_last, i_a_s, i_alpha, i_b, i_b_display, i_b_last, i_b_s, i_beta, i_c, i_c_last, i_c_s, i_d, i_d_display, i_d_integral, i_d_ref, i_error_limit, i_k_scaling, i_ki, i_kp, i_limit, I_MAX, i_output_max, i_q, i_q_display, i_q_integral, i_q_ref, i_reg_scaling, i_sample_1, i_sample_2, i_sample_offset, input_cmd, input_cmd_display, input_ref, ir_a, ir_a_display, ir_b, ir_c, l_didt_a, l_didt_a_display, l_didt_b, l_didt_c, l_phase, l_scaling, MESSAGE_SIZE, mode, motor_off, ONE_OVER_SQRT_THREE, output, p_error_limit, p_gravity, p_integral, p_k_scaling, p_ki, p_kp, p_max, p_min, p_output_max, p_output_min, p_reg_scaling, pwm_1, pwm_2, pwm_3, pwm_a, pwm_a_comp, pwm_b, pwm_b_comp, pwm_c, pwm_c_comp, PWM_CHANNEL_A, PWM_CHANNEL_B, PWM_CHANNEL_C, PWM_CHANNEL_D, pwm_counter, PWM_HALF, PWM_MAX, pwm_state, r_phase, r_scaling, s_error_limit, s_integral, s_k_scaling, s_ki, s_kp, s_output_max, s_reg_count, s_reg_rate, s_reg_scaling, SAMPLE_1_OFFSET, SAMPLE_2_OFFSET, sample_state_1, sample_state_2, sample_trigger, SAMPLE_WINDOW, sin_theta, speed, speed_display, speed_max, speed_min, speed_scale, SQRT_THREE_OVER_TWO, table_counter, test_oscillator(), TEST_pin_hi, TEST_pin_lo, theta, theta_90, theta_int, TWO_OVER_SQRT_THREE, u_a, u_a_display, u_b, u_c, u_scaling, UART_DATA_REGISTER, UART_STATUS_RECIEVE_TEST, v_a, v_a_display, v_alpha, v_b, v_b_display, v_beta, v_bus, v_bus_min, v_c, v_d, v_limit, v_mag_squared, V_MAX, V_MAX_SQUARED, v_q, valid_byte, variable_table, VARIABLE_TABLE_SIZE, window_1, window_2, write_eeprom(), and write_oscillator_cal().
{
//TEST_pin_hi;
// Motor Off function for updating EEPROM
if (v_bus < v_bus_min)
{
input_ref = 0;
}
else
{
input_ref = input_cmd;
}
if (motor_off > 0)
{
motor_off |= 2; //Motor PWM at 50%
pwm_a_comp = PWM_HALF;
pwm_b_comp = PWM_HALF;
pwm_c_comp = PWM_HALF;
sample_trigger = PWM_HALF;
}
// Clamp on Sample Trigger
if (sample_trigger >= PWM_MAX)
{
sample_trigger = PWM_MAX -1;
}
if (sample_trigger == 0)
{
sample_trigger = 1;
}
// Three Phase PWM and Sample Trigger Update
PWM_CHANNEL_A = PWM_MAX - pwm_a_comp; //Duty cycle
PWM_CHANNEL_B = PWM_MAX - pwm_b_comp; //Duty cycle
PWM_CHANNEL_C = PWM_MAX - pwm_c_comp; //Duty cycle
PWM_CHANNEL_D = PWM_MAX - sample_trigger; //Duty cycle
// Update EEPROM
// Write EEPROM function here. Non-reentrant so must disable interrupts
// bit 0 = motor off command, bit 1 = motor turned off,
// bit 2 = transfer variables back to EEPROM, bit 3 = Cal Oscillator
if (motor_off == 7)
{
write_eeprom();
}
// Test Oscillator
// bit 0 = motor off command, bit 1 = motor turned off,
// bit 2 = transfer variables back to EEPROM bit 3 = Cal Oscillator
if (motor_off == 11)
{
write_oscillator_cal();
test_oscillator();
}
// PWM Counter Update
pwm_counter++;
if (pwm_counter > 3)
{
pwm_counter = 0;
}
// Serial Communications Update
if (pwm_counter == 0)
{
if (data_toggle)
{
if (table_counter < (VARIABLE_TABLE_SIZE + EEPROM_TABLE_SIZE))
{
data_txd = variable_table[table_counter];
}
else
{
if (table_counter == (VARIABLE_TABLE_SIZE + EEPROM_TABLE_SIZE))
{
data_txd = 0; //0 at end of data
}
else
{
data_txd = 255; //The rest of the data is 255s
}
}
table_counter++;
if (table_counter > MESSAGE_SIZE)
{
table_counter = 0;
data_txd = 0; //0 at beginning of data
}
UART_DATA_REGISTER = data_txd;
data_toggle = 0;
}
else
{
if (count_dir == 0)
{
counter++;
if (counter>254)
{
count_dir = 1;
}
}
else
{
counter--;
if (counter<1)
{
count_dir = 0;
}
}
data_txd = variable_table[data_watch];
if (data_txd > 254)
{
data_txd = 254; // Clip data
}
UART_DATA_REGISTER = data_txd;
data_toggle = 1;
}
}
byte_timeout++;
// if (input_state == 1)
{
if (UART_STATUS_RECIEVE_TEST) // Receive buffer full?
{
data_rxd = UART_DATA_REGISTER; // valid start bit
valid_byte++;
}
if ( byte_timeout >= 32500) // 32500/15625Hz/2 = 1sec
{
valid_byte=0;
byte_timeout=0;
}
if (valid_byte == 3)
{
if (eeprom_number < EEPROM_TABLE_SIZE)
{
variable_table[eeprom_number + VARIABLE_TABLE_SIZE] = data_rxd;
}
valid_byte=0;
if ((eeprom_number == 254)&(data_rxd == 254))
{
// Motor off command and variables ready for write
motor_off = 5;
eeprom_number = 0;
}
if ((eeprom_number == 255)&(data_rxd == 255))
{
// Motor off command and calibrate oscillator
motor_off = 9;
eeprom_number = 0;
}
}
if (valid_byte == 1)
{
eeprom_number = data_rxd;
valid_byte++;
}
}
// Limit on Scaling variables (0 to 7)
speed_scale = speed_scale & 0x07;
p_reg_scaling = p_reg_scaling & 0x07;
p_k_scaling = p_k_scaling & 0x07;
s_reg_scaling = s_reg_scaling & 0x07;
s_k_scaling = s_k_scaling & 0x07;
i_reg_scaling = i_reg_scaling & 0x07;
i_k_scaling = i_k_scaling & 0x07;
u_scaling = u_scaling & 0x07;
r_scaling = r_scaling & 0x07;
l_scaling = l_scaling & 0x07;
if (v_limit > V_MAX)
{
v_limit = V_MAX;
}
if (i_limit > I_MAX)
{
i_limit = I_MAX;
}
// Sensorless FOC Routines (Cycles through 1 of 4 each ISR)
switch (pwm_counter)
{
case 0: //
// TEST_pin_hi;
// Update Angle
theta_int += speed;
theta = (theta_int>>speed_scale) & 0xFF;
// 90 Degrees = 256/360*90=64
theta_90 = (theta+64) & 0xFF;
if ((theta < 64) || (theta > 192))
{
TEST_pin_hi;
}
else
{
TEST_pin_lo;
}
// Sine and Cosine Lookup
sin_theta = pgm_read_byte(&(sine_table[theta]));
cos_theta = pgm_read_byte(&(sine_table[theta_90]));
// Phase Current Updates
// Phase Currents from last loop update
i_a_last = i_a;
i_b_last = i_b;
i_c_last = i_c;
// Phase Currents out to main loop
i_a = i_a_s; //0.075A/count
i_b = i_b_s;
i_c = i_c_s;
// Speed and Current Limit Update
//Recalc limits in case they have changed from Config Utility
p_min = (speed_min<<p_reg_scaling);
p_max = (speed_max<<p_reg_scaling);
s_output_max = (i_limit<<s_reg_scaling); // Calculated max current
i_output_max = (v_limit<<i_reg_scaling);
// Display Variables Update
v_a_display = v_a + HALF_SCALE;
v_b_display = v_b + HALF_SCALE;
i_a_display = i_a_s + HALF_SCALE;
i_b_display = i_b_s + HALF_SCALE;
u_a_display = u_a + HALF_SCALE;
ir_a_display = ir_a + HALF_SCALE;
l_didt_a_display = l_didt_a + HALF_SCALE;
e_a_display = e_a + HALF_SCALE;
i_d_display = i_d + HALF_SCALE;
i_q_display = i_q + HALF_SCALE;
e_d_display = e_d + HALF_SCALE;
input_cmd = input_cmd_display - HALF_SCALE;
//Speed Display uses half value to fit signed number on Variable plot
speed_display = speed + HALF_SCALE;
// Speed Regulator
if (mode != 2)
{
s_integral = 0;
}
s_reg_count++;
if (s_reg_count >= s_reg_rate)
{
s_reg_count = 0;
error = input_ref - speed;
if(error>s_error_limit)
{
error=s_error_limit;
}
if(error<-s_error_limit)
{
error=-s_error_limit;
}
output = (error * s_kp)>>s_k_scaling; //Kp
comp_ki = (error * s_ki)>>s_k_scaling; // Ki
s_integral += comp_ki;
if (s_integral < -s_output_max)
{
s_integral = -s_output_max;
}
if (s_integral > s_output_max)
{
s_integral = s_output_max;
}
output += s_integral;
if (output < -s_output_max)
{
output = -s_output_max;
}
if (output > s_output_max)
{
output = s_output_max;
}
i_d_ref = 0;
i_q_ref = output>>s_reg_scaling;
}
// ADC Sample
adc_user_sample = ADCA_CH0_RES;
ADCA_CH0_MUXCTRL = ADC_MUX_VBUS;
// Sample 1 PWM correction
switch (pwm_1)
{
case 1: // c (001) 1
pwm_a_comp = pwm_a;
pwm_b_comp = pwm_b;
pwm_c_comp = pwm_c + correction_1;
break;
case 2: // b (010) 2
pwm_a_comp = pwm_a;
pwm_b_comp = pwm_b + correction_1;
pwm_c_comp = pwm_c;
break;
case 4: // a (100) 4
pwm_a_comp = pwm_a + correction_1;
pwm_b_comp = pwm_b;
pwm_c_comp = pwm_c;
break;
default:
pwm_a_comp = PWM_HALF;
pwm_b_comp = PWM_HALF;
pwm_c_comp = PWM_HALF;
break;
}
switch (pwm_2)
{
case 1: // c (001) 1
sample_trigger = pwm_c_comp + SAMPLE_1_OFFSET;
break;
case 2: // b (010) 2
sample_trigger = pwm_b_comp + SAMPLE_1_OFFSET;
break;
case 4: // a (100) 4
sample_trigger = pwm_a_comp + SAMPLE_1_OFFSET;
break;
default:
sample_trigger = PWM_HALF;
break;
}
//TEST_pin_lo;
break;
case 1: //
//TEST_pin_hi;
// Back EMF Calculation
// Phase voltage
u_a = (v_a * v_bus)>>u_scaling; // 0.06V/count
u_b = (v_b * v_bus)>>u_scaling;
u_c = (v_c * v_bus)>>u_scaling;
// r_phase is 0.00625 Ohms/count
// 0.225 Ohms/0.00625 ohms/count = 36
ir_a = (i_a * r_phase)>>r_scaling; // 0.06V/count
ir_b = (i_b * r_phase)>>r_scaling;
ir_c = (i_c * r_phase)>>r_scaling;
l_didt_a = ((i_a - i_a_last) * l_phase)>>l_scaling; // 0.06V/count
l_didt_b = ((i_b - i_b_last) * l_phase)>>l_scaling;
l_didt_c = ((i_c - i_c_last) * l_phase)>>l_scaling;
e_a = u_a - ir_a - l_didt_a;
e_b = u_b - ir_b - l_didt_b;
e_c = u_c - ir_c - l_didt_c;
// Current 3 => 2 Clarke Transform
i_alpha =i_a;
i_beta=(((i_a*ONE_OVER_SQRT_THREE)/2)+i_b*TWO_OVER_SQRT_THREE)/128;
// Current Vector Rotation - Park Transform
i_d = (((i_alpha * cos_theta)) + ((i_beta * sin_theta)))/128;
i_q = (-((i_alpha * sin_theta)) + ((i_beta * cos_theta)))/128;
// Current Command
if (mode == 0)
{
i_d_ref = 0; // Field Weakening not implemented
i_q_ref = 0;
i_d_integral = 0;
i_q_integral = 0;
}
if (mode == 1)
{
i_d_ref = 0; // Field Weakening not implemented
i_q_ref = input_ref;
if ( input_ref > i_limit)
{
i_q_ref = i_limit;
}
if ( input_ref < -i_limit)
{
i_q_ref = -i_limit;
}
if (input_ref == 0)
{
i_d_integral = 0;
i_q_integral = 0;
}
}
// ADC Sample - v_bus
v_bus = ADCA_CH0_RES;
ADCA_CH0_MUXCTRL = ADC_MUX_I;
// Sample 2 PWM correction
switch (pwm_3)
{
case 1: // c (001) 1
pwm_a_comp = pwm_a;
pwm_b_comp = pwm_b;
pwm_c_comp = pwm_c - correction_2;
break;
case 2: // b (010) 2
pwm_a_comp = pwm_a;
pwm_b_comp = pwm_b - correction_2;
pwm_c_comp = pwm_c;
break;
case 4: // a (100) 4
pwm_a_comp = pwm_a - correction_2;
pwm_b_comp = pwm_b;
pwm_c_comp = pwm_c;
break;
default:
pwm_a_comp = PWM_HALF;
pwm_b_comp = PWM_HALF;
pwm_c_comp = PWM_HALF;
break;
}
switch (pwm_2)
{
case 1: // c (001) 1
sample_trigger = pwm_c_comp - SAMPLE_2_OFFSET;
break;
case 2: // b (010) 2
sample_trigger = pwm_b_comp - SAMPLE_2_OFFSET;
break;
case 4: // a (100) 4
sample_trigger = pwm_a_comp - SAMPLE_2_OFFSET;
break;
default:
sample_trigger = PWM_HALF;
break;
}
//TEST_pin_lo;
break;
case 2: //
//TEST_pin_hi;
// Clarke Transform 3 => 2 Back EMF
e_alpha =e_a;
e_beta=(((e_a*ONE_OVER_SQRT_THREE)/2)+e_b*TWO_OVER_SQRT_THREE)/128;
// Park Transform - Vector Rotation - Back EMF
e_d = (((e_alpha * cos_theta)) + ((e_beta * sin_theta)))/128;
e_q = (-((e_alpha * sin_theta)) + ((e_beta * cos_theta)))/128;
// i_d regulator
error = i_d_ref - i_d;
if(error>i_error_limit)
{
error=i_error_limit;
}
if(error<-i_error_limit)
{
error=-i_error_limit;
}
output = (error*i_kp)>>i_k_scaling; //Kp
comp_ki = (error * i_ki)>>i_k_scaling; // Ki
i_d_integral += comp_ki;
if (i_d_integral < -i_output_max)
{
i_d_integral = -i_output_max;
}
if (i_d_integral > i_output_max)
{
i_d_integral = i_output_max;
}
output += i_d_integral;
if (output < -i_output_max)
{
output = -i_output_max;
}
if (output > i_output_max)
{
output = i_output_max;
}
v_d = output>>i_reg_scaling;
// i_q regulator
error = i_q_ref - i_q;
if(error>i_error_limit)
{
error=i_error_limit;
}
if(error<-i_error_limit)
{
error=-i_error_limit;
}
output = (error * i_kp)>>i_k_scaling; //Kp
comp_ki = (error * i_ki)>>i_k_scaling; // Ki
i_q_integral += comp_ki;
if (i_q_integral < -i_output_max)
{
i_q_integral = -i_output_max;
}
if (i_q_integral > i_output_max)
{
i_q_integral = i_output_max;
}
output += i_q_integral;
if (output < -i_output_max)
{
output = -i_output_max;
}
if (output > i_output_max)
{
output = i_output_max;
}
v_q = output>>i_reg_scaling;
// Voltage Command
if (mode == 0)
{
v_d = 0;
v_q = input_ref;
if ( input_ref > v_limit)
{
v_q = v_limit;
}
if ( input_ref < -v_limit)
{
v_q = -v_limit;
}
}
// Voltage Clamp
v_mag_squared = (v_d * v_d) + (v_q * v_q);
// Test for outside the unit circle
// if true put in voltage mode
if (v_mag_squared > V_MAX_SQUARED)
{
v_d = 0;
if (v_q > 0)
{
v_q = v_limit;
}
else
{
v_q = -v_limit;
}
}
// ADC Sample
i_sample_1 = ADCA_CH0_RES + i_sample_offset;
ADCA_CH0_MUXCTRL = ADC_MUX_I;
// Current 1 Sample Calculations
switch (sample_state_1)
{
case 1: // V(001) = I_c
i_c_s = i_sample_1 - HALF_SCALE;
break;
case 2: // V(010) = I_b
i_b_s = i_sample_1 - HALF_SCALE;
break;
case 3: // V(011) = -I_a
i_a_s = HALF_SCALE - i_sample_1;
break;
case 4: // V(100) = I_a
i_a_s = i_sample_1 - HALF_SCALE;
break;
case 5: // V(101) = -I_b
i_b_s = HALF_SCALE - i_sample_1;
break;
case 6: // V(110) = -I_c
i_c_s = HALF_SCALE - i_sample_1;
break;
}
// Sample 2 PWM "anti-correction"
switch (pwm_3)
{
case 1: // c (001) 1
pwm_a_comp = pwm_a;
pwm_b_comp = pwm_b;
pwm_c_comp = pwm_c + correction_2;
break;
case 2: // b (010) 2
pwm_a_comp = pwm_a;
pwm_b_comp = pwm_b + correction_2;
pwm_c_comp = pwm_c;
break;
case 4: // a (100) 4
pwm_a_comp = pwm_a + correction_2;
pwm_b_comp = pwm_b;
pwm_c_comp = pwm_c;
break;
default:
pwm_a_comp = PWM_HALF;
pwm_b_comp = PWM_HALF;
pwm_c_comp = PWM_HALF;
break;
}
switch (pwm_2)
{
case 1: // c (001) 1
sample_trigger = pwm_c_comp - SAMPLE_2_OFFSET;
break;
case 2: // b (010) 2
sample_trigger = pwm_b_comp - SAMPLE_2_OFFSET;
break;
case 4: // a (100) 4
sample_trigger = pwm_a_comp - SAMPLE_2_OFFSET;
break;
default:
sample_trigger = PWM_HALF;
break;
}
//TEST_pin_lo;
break;
case 3: //
//TEST_pin_hi;
// Back EMF PLL
if (v_q == 0)
{
p_integral = 0;
}
if (v_q > 0) // Positive speed values
{
error = -e_d - p_gravity;
p_output_min = p_min;
p_output_max = p_max;
}
else // Negative speed values
{
error = e_d + p_gravity;
p_output_min = -p_max;
p_output_max = -p_min;
}
if(error>p_error_limit)
{
error=p_error_limit;
}
if(error<-p_error_limit)
{
error=-p_error_limit;
}
output = (error * p_kp)>>p_k_scaling; //Kp
comp_ki = (error * p_ki)>>p_k_scaling; // Ki
p_integral += comp_ki;
if (p_integral < p_output_min)
{
p_integral = p_output_min;
}
if (p_integral > p_output_max)
{
p_integral = p_output_max;
}
output += p_integral;
if (output < p_output_min)
{
output = p_output_min;
}
if (output > p_output_max)
{
output = p_output_max;
}
speed = output>>p_reg_scaling;
// Inverse Park Transform - Vector Rotation - Voltage
v_alpha = (((v_d * cos_theta)) - ((v_q * sin_theta)))/128;
v_beta = (((v_d * sin_theta)) + ((v_q * cos_theta)))/128;
// Inverse Clarke Transform - 2 => 3 - Voltage
v_a = v_alpha;
v_b = (-(v_alpha*128)+((v_beta*SQRT_THREE_OVER_TWO)))/256;
v_c = (-(v_alpha*128)-((v_beta*SQRT_THREE_OVER_TWO)))/256;
// ADC Sample
i_sample_2 = ADCA_CH0_RES + i_sample_offset;
ADCA_CH0_MUXCTRL = adc_user_channel;
// Current 2 Sample Calculation
switch (sample_state_2)
{
case 1: // V(001) = I_c
i_c_s = i_sample_2 - HALF_SCALE;
break;
case 2: // V(010) = I_b
i_b_s = i_sample_2 - HALF_SCALE;
break;
case 3: // V(011) = -I_a
i_a_s = HALF_SCALE - i_sample_2;
break;
case 4: // V(100) = I_a
i_a_s = i_sample_2 - HALF_SCALE;
break;
case 5: // V(101) = -I_b
i_b_s = HALF_SCALE - i_sample_2;
break;
case 6: // V(110) = -I_c
i_c_s = HALF_SCALE - i_sample_2;
break;
}
// Three phase current calculation
if ((sample_state_1 != 3) && (sample_state_1 != 4))
{
if ((sample_state_2 != 3) && (sample_state_2 != 4))
{
i_a_s = -(i_c_s + i_b_s);
}
}
if ((sample_state_1 != 2) && (sample_state_1 != 5))
{
if ((sample_state_2 != 2) && (sample_state_2 != 5))
{
i_b_s = -(i_c_s + i_a_s);
}
}
if ((sample_state_1 != 1) && (sample_state_1 != 6))
{
if ((sample_state_2 != 1) && (sample_state_2 != 6))
{
i_c_s = -(i_a_s + i_b_s);
}
}
// PWM State and Sample windows Calculation
pwm_a = PWM_HALF + v_a;
pwm_b = PWM_HALF + v_b;
pwm_c = PWM_HALF + v_c;
pwm_state = 0;
if (pwm_a >= PWM_HALF)
{
pwm_state = 4;
}
if (pwm_b >= PWM_HALF)
{
pwm_state |= 2;
}
if (pwm_c >= PWM_HALF)
{
pwm_state |= 1;
}
switch (pwm_state)
{
case 1: // V(001)
sample_state_1 = 1; // V(001) = I_c
if (pwm_a < pwm_b)
{
sample_state_2 = 3; // V(011) = -I_a
window_1 = pwm_c - pwm_b;
window_2 = pwm_b - pwm_a;
pwm_1 = 1; // first sample 4 = A, 2 = B, 1 = C
pwm_2 = 2; // second sample 4 = A, 2 = B, 1 = C
pwm_3 = 4; // second sample 4 = A, 2 = B, 1 = C
}
else
{
sample_state_2 = 5; // V(101) = -I_b
window_1 = pwm_c - pwm_a;
window_2 = pwm_a - pwm_b;
pwm_1 = 1; // first sample 4 = A, 2 = B, 1 = C
pwm_2 = 4; // second sample 4 = A, 2 = B, 1 = C
pwm_3 = 2; // second sample 4 = A, 2 = B, 1 = C
}
break;
case 2: // V(010)
sample_state_1 = 2; // V(010) = I_b
pwm_1 = 2; // first sample 4 = A, 2 = B, 1 = C
if (pwm_c < pwm_a)
{
sample_state_2 = 6; // V(110) = -I_c
window_1 = pwm_b - pwm_a;
window_2 = pwm_a - pwm_c;
pwm_1 = 2; // first sample 4 = A, 2 = B, 1 = C
pwm_2 = 4; // second sample 4 = A, 2 = B, 1 = C
pwm_3 = 1; // second sample 4 = A, 2 = B, 1 = C
}
else
{
sample_state_2 = 3; // V(011) = -I_a
window_1 = pwm_b - pwm_c;
window_2 = pwm_c - pwm_a;
pwm_1 = 2; // first sample 4 = A, 2 = B, 1 = C
pwm_2 = 1; // second sample 4 = A, 2 = B, 1 = C
pwm_3 = 4; // second sample 4 = A, 2 = B, 1 = C
}
break;
case 4: // V(100)
sample_state_1 = 4; // V(100) = I_a
if (pwm_b < pwm_c)
{
sample_state_2 = 5; // V(101) = -I_b
window_1 = pwm_a - pwm_c;
window_2 = pwm_c - pwm_b;
pwm_1 = 4; // first sample 4 = A, 2 = B, 1 = C
pwm_2 = 1; // second sample 4 = A, 2 = B, 1 = C
pwm_3 = 2; // second sample 4 = A, 2 = B, 1 = C
}
else
{
sample_state_2 = 6; // V(110) = -I_c
window_1 = pwm_a - pwm_b;
window_2 = pwm_b - pwm_c;
pwm_1 = 4; // first sample 4 = A, 2 = B, 1 = C
pwm_2 = 2; // second sample 4 = A, 2 = B, 1 = C
pwm_3 = 1; // second sample 4 = A, 2 = B, 1 = C
}
break;
case 6: // V(110)
sample_state_2 = 6; // V(110) = -I_c
if (pwm_a > pwm_b)
{
sample_state_1 = 4; // V(100) = I_a
window_1 = pwm_a - pwm_b;
window_2 = pwm_b - pwm_c;
pwm_1 = 4; // first sample 4 = A, 2 = B, 1 = C
pwm_2 = 2; // second sample 4 = A, 2 = B, 1 = C
pwm_3 = 1; // second sample 4 = A, 2 = B, 1 = C
}
else
{
sample_state_1 = 2; // V(010) = I_b
window_1 = pwm_b - pwm_a;
window_2 = pwm_a - pwm_c;
pwm_1 = 2; // first sample 4 = A, 2 = B, 1 = C
pwm_2 = 4; // second sample 4 = A, 2 = B, 1 = C
pwm_3 = 1; // second sample 4 = A, 2 = B, 1 = C
}
break;
case 5: // V(101)
sample_state_2 = 5; // V(101) = -I_b
if (pwm_c > pwm_a)
{
sample_state_1 = 1; // V(001) = I_c
window_1 = pwm_c - pwm_a;
window_2 = pwm_a - pwm_b;
pwm_1 = 1; // first sample 4 = A, 2 = B, 1 = C
pwm_2 = 4; // second sample 4 = A, 2 = B, 1 = C
pwm_3 = 2; // second sample 4 = A, 2 = B, 1 = C
}
else
{
sample_state_1 = 4; // V(100) = I_a
window_1 = pwm_a - pwm_c;
window_2 = pwm_c - pwm_b;
pwm_1 = 4; // first sample 4 = A, 2 = B, 1 = C
pwm_2 = 1; // second sample 4 = A, 2 = B, 1 = C
pwm_3 = 2; // second sample 4 = A, 2 = B, 1 = C
}
break;
case 3: // V(011)
sample_state_2 = 3; // V(011) = -I_a
if (pwm_b > pwm_c)
{
sample_state_1 = 2; // V(010) = I_b
window_1 = pwm_b - pwm_c;
window_2 = pwm_c - pwm_a;
pwm_1 = 2; // first sample 4 = A, 2 = B, 1 = C
pwm_2 = 1; // second sample 4 = A, 2 = B, 1 = C
pwm_3 = 4; // second sample 4 = A, 2 = B, 1 = C
}
else
{
sample_state_1 = 1; // V(001) = I_c
window_1 = pwm_c - pwm_b;
window_2 = pwm_b - pwm_a;
pwm_1 = 1; // first sample 4 = A, 2 = B, 1 = C
pwm_2 = 2; // second sample 4 = A, 2 = B, 1 = C
pwm_3 = 4; // second sample 4 = A, 2 = B, 1 = C
}
break;
default:
break;
}
correction_1 = 0;
correction_2 = 0;
if (window_1 < SAMPLE_WINDOW)
{
correction_1 = SAMPLE_WINDOW - window_1;
}
if (window_2 < SAMPLE_WINDOW)
{
correction_2 = SAMPLE_WINDOW - window_2;
}
// Sample 1 PWM "anti-correction"
switch (pwm_1)
{
case 1: // c (001) 1
pwm_a_comp = pwm_a;
pwm_b_comp = pwm_b;
pwm_c_comp = pwm_c - correction_1;
break;
case 2: // b (010) 2
pwm_a_comp = pwm_a;
pwm_b_comp = pwm_b - correction_1;
pwm_c_comp = pwm_c;
break;
case 4: // a (100) 4
pwm_a_comp = pwm_a - correction_1;
pwm_b_comp = pwm_b;
pwm_c_comp = pwm_c;
break;
default:
pwm_a_comp = PWM_HALF;
pwm_b_comp = PWM_HALF;
pwm_c_comp = PWM_HALF;
break;
}
switch (pwm_2)
{
case 1: // c (001) 1
sample_trigger = pwm_c_comp + SAMPLE_1_OFFSET;
break;
case 2: // b (010) 2
sample_trigger = pwm_b_comp + SAMPLE_1_OFFSET;
break;
case 4: // a (100) 4
sample_trigger = pwm_a_comp + SAMPLE_1_OFFSET;
break;
default:
sample_trigger = PWM_HALF;
break;
}
break;
default:
break;
}
// TEST_pin_lo;
}
| int main | ( | void | ) |
Main.
Performs all installation function calls then sits waiting for ISR
Definition at line 2077 of file AVR1636 - Firmware.c.
References calibrate_current(), init_adc(), init_eventsys(), init_interrupts(), init_oscillator(), init_pwm(), init_test_pin(), init_uart(), read_eeprom(), read_oscillator_cal(), and write_oscillator_cal().
{
init_oscillator();
init_test_pin();
init_pwm();
init_adc();
init_uart();
init_eventsys();
init_interrupts();
read_eeprom(); // Read the EEPROM contents once on power up
calibrate_current();
read_oscillator_cal();
write_oscillator_cal();
while(1)
{
//Application code here
}
}| void read_eeprom | ( | void | ) |
Reads EEPROM values.
EEPROM values are used for configuration of motor parameters These values are configured and updated from the PC based Motor Control Configuration Utility
Definition at line 679 of file AVR1636 - Firmware.c.
References EEPROM_TABLE_SIZE, table_counter, variable_table, and VARIABLE_TABLE_SIZE.
Referenced by main().
{
cli();
table_counter = 0;
while (table_counter < EEPROM_TABLE_SIZE)
{
variable_table[VARIABLE_TABLE_SIZE + table_counter] =
eeprom_read_byte((uint8_t*)(table_counter));
table_counter++;
}
table_counter = 0;
sei();
}
| void read_oscillator_cal | ( | void | ) |
Reads Oscillator calibration value.
Reads in factory calibration value for 32Mhz oscillator and stores in RAM.
Definition at line 734 of file AVR1636 - Firmware.c.
References osc_cal.
Referenced by main().
{
osc_cal = ((DFLLRC32M_CALB & 0x1F)<<8) + DFLLRC32M_CALA;
}
| void test_oscillator | ( | void | ) |
Tests accuracy of Oscillator.
Compares to USB to UART bridge oscillator to internal oscillator PC sends a 0 byte at 300 baud, for a 30ms period count the number of PWM periods. 30ms/31.25us = 960 periods
Definition at line 774 of file AVR1636 - Firmware.c.
References motor_off, osc_error, PWM_PERIODS, RXD_PIN, RXD_PIN_0, RXD_PIN_1, and table_counter.
Referenced by ISR().
{
uint16_t osc_pwm_periods;
cli();
osc_pwm_periods = 0;
while ((PORTD_IN & RXD_PIN) == RXD_PIN_1 )
{
}
while ((PORTD_IN & RXD_PIN) == RXD_PIN_0 )
{
if((TCC0_INTFLAGS & TC0_CCDIF_bm) == TC0_CCDIF_bm)
{
TCC0_INTFLAGS |= TC0_CCDIF_bm;
osc_pwm_periods++;
}
}
osc_error = 128 + osc_pwm_periods - PWM_PERIODS;
motor_off = 0;
table_counter = 0;
sei();
}
| void write_eeprom | ( | void | ) |
Writes EEPROM values.
EEPROM values are used for configuration of motor parameters These values are configured and updated from the PC based Motor Control Configuration Utility
Definition at line 707 of file AVR1636 - Firmware.c.
References EEPROM_TABLE_SIZE, motor_off, table_counter, variable_table, and VARIABLE_TABLE_SIZE.
Referenced by ISR().
{
cli();
table_counter = 0;
while (table_counter < EEPROM_TABLE_SIZE)
{
eeprom_write_byte ((uint8_t*)(table_counter),
variable_table[VARIABLE_TABLE_SIZE + table_counter]);
table_counter++;
}
table_counter = 0;
motor_off = 0;
sei();
}
| void write_oscillator_cal | ( | void | ) |
Writes Oscillator calibration value.
Writes calibration value for 32Mhz oscillator.
Definition at line 751 of file AVR1636 - Firmware.c.
References osc_cal, and osc_cal_adj.
Referenced by ISR(), and main().
{
if (osc_cal_adj < 65)
{
DFLLRC32M_CALB = (((osc_cal + osc_cal_adj - 32)>>8) & 0x1F);
DFLLRC32M_CALA = ((osc_cal + osc_cal_adj - 32) & 0xFF);
}
}
| uint8_t adc_user_channel = 0 |
Definition at line 242 of file AVR1636 - Firmware.c.
Referenced by ISR().
| uint8_t adc_user_sample |
Definition at line 243 of file AVR1636 - Firmware.c.
Referenced by ISR().
| uint16_t byte_timeout |
Definition at line 209 of file AVR1636 - Firmware.c.
Referenced by ISR().
| int16_t comp_ki |
Definition at line 328 of file AVR1636 - Firmware.c.
Referenced by ISR().
| uint8_t correction_1 |
Definition at line 232 of file AVR1636 - Firmware.c.
Referenced by ISR().
| uint8_t correction_2 |
Definition at line 233 of file AVR1636 - Firmware.c.
Referenced by ISR().
| int8_t cos_theta |
Definition at line 247 of file AVR1636 - Firmware.c.
Referenced by ISR().
| uint8_t count_dir |
Definition at line 214 of file AVR1636 - Firmware.c.
Referenced by ISR().
| uint8_t data_rxd |
Definition at line 211 of file AVR1636 - Firmware.c.
Referenced by ISR().
| uint8_t data_toggle |
Definition at line 212 of file AVR1636 - Firmware.c.
Referenced by ISR().
| uint8_t data_txd |
Definition at line 210 of file AVR1636 - Firmware.c.
Referenced by ISR().
| int8_t e_a |
Definition at line 288 of file AVR1636 - Firmware.c.
Referenced by ISR().
| int8_t e_alpha |
Definition at line 292 of file AVR1636 - Firmware.c.
Referenced by ISR().
| int8_t e_b |
Definition at line 289 of file AVR1636 - Firmware.c.
Referenced by ISR().
| int8_t e_beta |
Definition at line 293 of file AVR1636 - Firmware.c.
Referenced by ISR().
| int8_t e_c |
Definition at line 290 of file AVR1636 - Firmware.c.
Referenced by ISR().
| int8_t e_d |
Definition at line 295 of file AVR1636 - Firmware.c.
Referenced by ISR().
| int8_t e_q |
Definition at line 296 of file AVR1636 - Firmware.c.
Referenced by ISR().
| uint8_t eeprom_number |
Definition at line 218 of file AVR1636 - Firmware.c.
Referenced by ISR().
| int16_t error |
Definition at line 327 of file AVR1636 - Firmware.c.
Referenced by ISR().
| int8_t i_a |
Definition at line 254 of file AVR1636 - Firmware.c.
Referenced by ISR().
| int8_t i_a_last |
Definition at line 262 of file AVR1636 - Firmware.c.
Referenced by ISR().
| int8_t i_a_s |
Definition at line 258 of file AVR1636 - Firmware.c.
Referenced by ISR().
| int8_t i_alpha |
Definition at line 252 of file AVR1636 - Firmware.c.
Referenced by ISR().
| int8_t i_b |
Definition at line 255 of file AVR1636 - Firmware.c.
Referenced by ISR().
| int8_t i_b_last |
Definition at line 263 of file AVR1636 - Firmware.c.
Referenced by ISR().
| int8_t i_b_s |
Definition at line 259 of file AVR1636 - Firmware.c.
Referenced by ISR().
| int8_t i_beta |
Definition at line 253 of file AVR1636 - Firmware.c.
Referenced by ISR().
| int8_t i_c |
Definition at line 256 of file AVR1636 - Firmware.c.
Referenced by ISR().
| int8_t i_c_last |
Definition at line 264 of file AVR1636 - Firmware.c.
Referenced by ISR().
| int8_t i_c_s |
Definition at line 260 of file AVR1636 - Firmware.c.
Referenced by ISR().
| int8_t i_d |
Definition at line 250 of file AVR1636 - Firmware.c.
Referenced by ISR().
| int16_t i_d_integral |
Definition at line 321 of file AVR1636 - Firmware.c.
Referenced by ISR().
| int8_t i_d_ref |
Definition at line 319 of file AVR1636 - Firmware.c.
Referenced by ISR().
| int16_t i_output_max |
Definition at line 323 of file AVR1636 - Firmware.c.
Referenced by ISR().
| int8_t i_q |
Definition at line 251 of file AVR1636 - Firmware.c.
Referenced by ISR().
| int16_t i_q_integral |
Definition at line 322 of file AVR1636 - Firmware.c.
Referenced by ISR().
| int8_t i_q_ref |
Definition at line 320 of file AVR1636 - Firmware.c.
Referenced by ISR().
| uint8_t i_sample_1 |
Definition at line 226 of file AVR1636 - Firmware.c.
Referenced by calibrate_current(), and ISR().
| uint8_t i_sample_2 |
Definition at line 227 of file AVR1636 - Firmware.c.
Referenced by calibrate_current(), and ISR().
| uint8_t i_sample_offset |
Definition at line 225 of file AVR1636 - Firmware.c.
Referenced by calibrate_current(), and ISR().
| int8_t input_cmd |
Definition at line 337 of file AVR1636 - Firmware.c.
Referenced by ISR().
| int8_t input_ref |
Definition at line 326 of file AVR1636 - Firmware.c.
Referenced by ISR().
| int8_t ir_a |
Definition at line 280 of file AVR1636 - Firmware.c.
Referenced by ISR().
| int8_t ir_b |
Definition at line 281 of file AVR1636 - Firmware.c.
Referenced by ISR().
| int8_t ir_c |
Definition at line 282 of file AVR1636 - Firmware.c.
Referenced by ISR().
| int8_t l_didt_a |
Definition at line 284 of file AVR1636 - Firmware.c.
Referenced by ISR().
| int8_t l_didt_b |
Definition at line 285 of file AVR1636 - Firmware.c.
Referenced by ISR().
| int8_t l_didt_c |
Definition at line 286 of file AVR1636 - Firmware.c.
Referenced by ISR().
| uint8_t motor_off |
Definition at line 221 of file AVR1636 - Firmware.c.
Referenced by ISR(), test_oscillator(), and write_eeprom().
| uint16_t osc_cal |
Definition at line 343 of file AVR1636 - Firmware.c.
Referenced by read_oscillator_cal(), and write_oscillator_cal().
| int16_t output |
Definition at line 329 of file AVR1636 - Firmware.c.
Referenced by ISR().
| int16_t p_integral |
Definition at line 306 of file AVR1636 - Firmware.c.
Referenced by ISR().
| int16_t p_max |
Definition at line 308 of file AVR1636 - Firmware.c.
Referenced by ISR().
| int16_t p_min |
Definition at line 307 of file AVR1636 - Firmware.c.
Referenced by ISR().
| int16_t p_output_max |
Definition at line 310 of file AVR1636 - Firmware.c.
Referenced by ISR().
| int16_t p_output_min |
Definition at line 309 of file AVR1636 - Firmware.c.
Referenced by ISR().
| const int8_t sine_table [256] PROGMEM |
Definition at line 74 of file AVR1636 - Firmware.c.
| uint8_t pwm_1 |
Definition at line 234 of file AVR1636 - Firmware.c.
Referenced by ISR().
| uint8_t pwm_2 |
Definition at line 235 of file AVR1636 - Firmware.c.
Referenced by ISR().
| uint8_t pwm_3 |
Definition at line 236 of file AVR1636 - Firmware.c.
Referenced by ISR().
| uint8_t pwm_a |
Definition at line 299 of file AVR1636 - Firmware.c.
Referenced by ISR().
| uint8_t pwm_a_comp |
Definition at line 237 of file AVR1636 - Firmware.c.
Referenced by ISR().
| uint8_t pwm_b |
Definition at line 300 of file AVR1636 - Firmware.c.
Referenced by ISR().
| uint8_t pwm_b_comp |
Definition at line 238 of file AVR1636 - Firmware.c.
Referenced by ISR().
| uint8_t pwm_c |
Definition at line 301 of file AVR1636 - Firmware.c.
Referenced by ISR().
| uint8_t pwm_c_comp |
Definition at line 239 of file AVR1636 - Firmware.c.
Referenced by ISR().
| uint8_t pwm_counter = 0 |
Definition at line 206 of file AVR1636 - Firmware.c.
Referenced by calibrate_current(), and ISR().
| uint8_t pwm_state |
Definition at line 303 of file AVR1636 - Firmware.c.
Referenced by ISR().
| int16_t s_integral |
Definition at line 314 of file AVR1636 - Firmware.c.
Referenced by ISR().
| int16_t s_output_max |
Definition at line 316 of file AVR1636 - Firmware.c.
Referenced by ISR().
| int16_t s_output_min |
Definition at line 315 of file AVR1636 - Firmware.c.
| uint8_t s_reg_count |
Definition at line 313 of file AVR1636 - Firmware.c.
Referenced by ISR().
| uint8_t sample_state_1 |
Definition at line 228 of file AVR1636 - Firmware.c.
Referenced by ISR().
| uint8_t sample_state_2 |
Definition at line 229 of file AVR1636 - Firmware.c.
Referenced by ISR().
| uint8_t sample_trigger |
Definition at line 302 of file AVR1636 - Firmware.c.
Referenced by ISR().
| int8_t sin_theta |
Definition at line 246 of file AVR1636 - Firmware.c.
Referenced by ISR().
| int16_t speed |
Definition at line 336 of file AVR1636 - Firmware.c.
Referenced by ISR().
| uint16_t table_counter = 0 |
Definition at line 346 of file AVR1636 - Firmware.c.
Referenced by ISR(), read_eeprom(), test_oscillator(), and write_eeprom().
| uint8_t theta_90 |
Definition at line 333 of file AVR1636 - Firmware.c.
Referenced by ISR().
| uint16_t theta_int |
Definition at line 332 of file AVR1636 - Firmware.c.
Referenced by ISR().
| int8_t u_a |
Definition at line 276 of file AVR1636 - Firmware.c.
Referenced by ISR().
| int8_t u_b |
Definition at line 277 of file AVR1636 - Firmware.c.
Referenced by ISR().
| int8_t u_c |
Definition at line 278 of file AVR1636 - Firmware.c.
Referenced by ISR().
| int8_t v_a |
Definition at line 271 of file AVR1636 - Firmware.c.
Referenced by ISR().
| int8_t v_alpha |
Definition at line 269 of file AVR1636 - Firmware.c.
Referenced by ISR().
| int8_t v_b |
Definition at line 272 of file AVR1636 - Firmware.c.
Referenced by ISR().
| int8_t v_beta |
Definition at line 270 of file AVR1636 - Firmware.c.
Referenced by ISR().
| int8_t v_c |
Definition at line 273 of file AVR1636 - Firmware.c.
Referenced by ISR().
| int8_t v_d |
Definition at line 267 of file AVR1636 - Firmware.c.
Referenced by ISR().
| uint16_t v_mag_squared |
Definition at line 340 of file AVR1636 - Firmware.c.
Referenced by ISR().
| int8_t v_q |
Definition at line 268 of file AVR1636 - Firmware.c.
Referenced by ISR().
| uint8_t valid_byte |
Definition at line 217 of file AVR1636 - Firmware.c.
Referenced by ISR().
Definition at line 349 of file AVR1636 - Firmware.c.
Referenced by ISR(), read_eeprom(), and write_eeprom().
| uint8_t window_1 |
Definition at line 230 of file AVR1636 - Firmware.c.
Referenced by ISR().
| uint8_t window_2 |
Definition at line 231 of file AVR1636 - Firmware.c.
Referenced by ISR().